home *** CD-ROM | disk | FTP | other *** search
- /* ALFA STDWIN -- DRAWING. */
-
- #include "alfa.h"
-
- /* Cause a redraw of part of a window. */
-
- /*ARGSUSED*/
- void
- wchange(win, left, top, right, bottom)
- WINDOW *win;
- int left, top;
- int right, bottom;
- {
- int id= win - winlist;
- int i;
-
- if (id < 0 || id >= MAXWINDOWS || !win->open)
- return;
- top -= win->offset;
- bottom -= win->offset;
- if (top < win->top)
- top= win->top;
- if (bottom > win->bottom)
- bottom= win->bottom;
- for (i= top; i < bottom; ++i)
- uptodate[i]= FALSE;
- _wnewtitle(win);
- }
-
- /* (Try to) make sure a particular part of a window is visible,
- by scrolling in distant parts if necessary. */
-
- static void scrollupdate();
-
- /*ARGSUSED*/
- void
- wshow(win, left, top, right, bottom)
- WINDOW *win;
- int left, top;
- int right, bottom;
- {
- int id= win - winlist;
- int offset;
- int extra;
- int dv;
-
- if (id < 0 || id >= MAXWINDOWS || !win->open)
- return;
- extra= ( (win->bottom - win->top) - (bottom - top) ) / 2;
- if (extra < 0)
- extra= 0;
- offset= win->offset;
- if (bottom > win->bottom + offset)
- offset= bottom - win->bottom + extra;
- if (top < win->top + offset)
- offset= top - win->top - extra;
- if (win->top + offset < 0)
- offset= -win->top;
- dv= offset - win->offset;
- if (dv == 0)
- return;
- win->offset= offset;
- /* Now we'll use top, bottom to indicate the changed part. */
- top= win->top;
- bottom= win->bottom;
- scrollupdate(top, bottom, dv);
- trmscrollup(top, bottom-1, dv);
- }
-
- /* Similar, but by giving an explicit new origin */
-
- /*ARGSUSED*/
- void
- wsetorigin(win, h, v)
- WINDOW *win;
- int h, v;
- {
- int id= win - winlist;
- int top, bottom;
- int dv;
-
- if (id < 0 || id >= MAXWINDOWS || !win->open)
- return;
- dv = (v - win->top) - win->offset;
- if (dv == 0)
- return;
- win->offset += dv;
- top = win->top;
- bottom = win->bottom;
- scrollupdate(top, bottom, dv);
- trmscrollup(top, bottom-1, dv);
- }
-
- /* Scroll the update bits */
-
- static void
- scrollupdate(top, bottom, dv)
- int top, bottom;
- int dv;
- {
- int i;
- for (i= top; i < bottom; ++i) {
- #ifdef BUGGY
- /* This code no longer works --
- should copy the actual contents as well. */
- if (i+dv >= top && i+dv < bottom && uptodate[i+dv])
- uptodate[i]= TRUE;
- else
- #endif
- uptodate[i]= FALSE;
- }
- }
-
- /* Set the caret (cursor) position. */
-
- void
- wsetcaret(win, h, v)
- WINDOW *win;
- int h, v;
- {
- win->curh= h;
- win->curv= v;
- wshow(win, h, v, h+1, v+1);
- }
-
- /* Remove the caret altogether. */
-
- void
- wnocaret(win)
- WINDOW *win;
- {
- win->curh= win->curv= -1;
- }
-
- /* Cause a redraw of the window 's title bar. */
-
- void
- _wnewtitle(win)
- WINDOW *win;
- {
- if (win->top > 0)
- uptodate[win->top-1]= FALSE;
- }
-
- static char *textline[MAXLINES];
- static short textlen[MAXLINES];
- static char texttouched[MAXLINES];
-
- static TEXTATTR draw_saveattr;
- static WINDOW *draw_win;
-
- /* Compute the smallest rectangle that needs an update.
- As a side effect, uptodate is set to TRUE for the affected lines,
- and the lines are cleared and set to touched
- (but no actual output is performed).
- Return FALSE if the rectangle is empty. */
-
- bool
- wgetchange(win, pleft, ptop, pright, pbottom)
- WINDOW *win;
- int *pleft, *ptop, *pright, *pbottom;
- {
- int top= win->bottom;
- int bottom= win->top;
- int i;
-
- for (i= win->top; i < win->bottom; ++i) {
- if (!uptodate[i]) {
- texttouched[i]= TRUE;
- textlen[i]= 0;
- uptodate[i]= TRUE;
- if (top > i)
- top= i;
- bottom= i+1;
- }
- }
- if (top > bottom) {
- *pleft= *pright= *ptop= *pbottom= 0;
- return FALSE;
- }
- else {
- *pleft= 0;
- *pright= columns;
- *ptop= top + win->offset;
- *pbottom= bottom + win->offset;
- return TRUE;
- }
- }
-
- void
- wupdate(win)
- WINDOW *win;
- {
- int left, top, right, bottom;
- int i;
-
- wgetchange(win, &left, &top, &right, &bottom);
-
- wbegindrawing(win);
-
- if (win->drawproc != NULL)
- (*win->drawproc)(win, 0, top, columns, bottom);
-
- wenddrawing(win);
- }
-
- void
- wbegindrawing(win)
- WINDOW *win;
- {
- int i;
-
- if (draw_win != NULL)
- wenddrawing(draw_win); /* Finish previous job */
-
- for (i= win->top; i < win->bottom; ++i) {
- if (textline[i] == NULL)
- textline[i]= malloc((size_t) (columns+1));
- }
-
- draw_saveattr= wattr;
- wattr= win->attr;
- draw_win= win;
- }
-
- void
- wenddrawing(win)
- WINDOW *win;
- {
- int i;
-
- if (draw_win != win) {
- return; /* Bad call */
- }
-
- for (i= win->top; i < win->bottom; ++i) {
- if (texttouched[i]) {
- texttouched[i]= FALSE;
- textline[i][textlen[i]]= EOS;
- trmputdata(i, i, 0, textline[i]);
- }
- }
-
- wattr= draw_saveattr;
- draw_win= NULL;
- }
-
- void
- wdrawtitle(win)
- WINDOW *win;
- {
- int titline= win->top - 1;
- char buf[256];
- char *title= win->title == NULL ? "" : win->title;
- int tlen= (int)strlen(title);
- int space= columns-tlen;
- int mask= (win == front) ? 0200 : 0;
- int k;
-
- for (k= 0; k < space/2 - 1; ++k)
- buf[k]= '-'|mask;
- buf[k++]= ' '|mask;
- while (k < columns && *title != EOS)
- buf[k++]= *title++|mask;
- if (k < columns)
- buf[k++]= ' '|mask;
- while (k < columns)
- buf[k++]= '-'|mask;
- buf[k]= EOS;
- trmputdata(titline, titline, 0, buf);
- uptodate[titline]= TRUE;
- }
-
- int
- wdrawtext(h, v, str, len)
- int h, v;
- char *str;
- int len;
- {
- int k;
- int mask= (wattr.style == 0) ? 0 : 0200;
- char *text;
- WINDOW *win= draw_win;
-
- if (len < 0)
- len= (int)strlen(str);
- v -= win->offset;
- if (v < win->top || v >= win->bottom || h >= columns || len == 0)
- return h+wtextwidth(str, len);
- text= textline[v];
- k= textlen[v];
- while (k < h)
- text[k++]= ' ';
- while (len > 0) {
- #define APPC(c) \
- if (h >= 0) text[h]= (c) | mask; if (++h >= columns) break
- unsigned char c= *str++;
- --len;
- if (c < ' ') {
- APPC('^');
- APPC(c | '@');
- }
- else if (c < 0177) {
- APPC(c);
- }
- else if (c < 0200) {
- APPC('^');
- APPC('?');
- }
- else {
- APPC('\\');
- APPC('0' | ((c>>3) & 07));
- APPC('0' | ((c>>6) & 07));
- APPC('0' | (c & 07));
- }
- #undef APPC
- }
- if (h > textlen[v])
- textlen[v]= h;
- texttouched[v]= TRUE;
- return h+len;
- }
-
- int
- wdrawchar(h, v, c)
- int h, v;
- int c;
- {
- char cbuf[2];
- cbuf[0]= c;
- cbuf[1]= EOS;
- return wdrawtext(h, v, cbuf, 1);
- }
-
- void
- wgetwintextattr(win, attr)
- WINDOW *win;
- TEXTATTR *attr;
- {
- *attr= win->attr;
- }
-
- void
- wsetwintextattr(win, attr)
- WINDOW *win;
- TEXTATTR *attr;
- {
- win->attr= *attr;
- }
-
- /* Non-text drawing dummy functions: */
-
- /*ARGSUSED*/
- void
- wdrawline(h1, v1, h2, v2)
- int h1, v1, h2, v2;
- {
- }
-
- /*ARGSUSED*/
- void
- wxorline(h1, v1, h2, v2)
- int h1, v1, h2, v2;
- {
- }
-
- /*ARGSUSED*/
- void
- wdrawcircle(h, v, radius)
- int h, v;
- int radius;
- {
- }
-
- /*ARGSUSED*/
- void
- wdrawelarc(h, v, radh, radv, ang1, ang2)
- int h, v;
- int radh, radv;
- int ang1, ang2;
- {
- }
-
- /*ARGSUSED*/
- void
- wdrawbox(left, top, right, bottom)
- int left, top, right, bottom;
- {
- }
-
- /*ARGSUSED*/
- void
- wpaint(left, top, right, bottom)
- int left, top, right, bottom;
- {
- }
-
- /*ARGSUSED*/
- void
- wshade(left, top, right, bottom, percentage)
- int left, top, right, bottom;
- int percentage;
- {
- }
-
- /*ARGSUSED*/
- void
- winvert(left, top, right, bottom)
- int left, top, right, bottom;
- {
- WINDOW *win= draw_win;
- int h, v;
-
- if (left < 0)
- left= 0;
- if (right >= columns)
- right= columns;
- if (left >= right)
- return;
- top -= win->offset;
- bottom -= win->offset;
- if (top < win->top)
- top= win->top;
- if (bottom > win->bottom)
- bottom= win->bottom;
- for (v= top; v < bottom; ++v) {
- int k= textlen[v];
- char *text= textline[v];
- if (k < right) {
- do {
- text[k++]= ' ';
- } while (k < right);
- textlen[v]= k;
- }
- for (k= left; k < right; ++k)
- text[k] ^= 0200;
- texttouched[v]= TRUE;
- }
- }
-
- /*ARGSUSED*/
- void
- werase(left, top, right, bottom)
- int left, top, right, bottom;
- {
- WINDOW *win= draw_win;
- int h, v;
-
- if (left < 0)
- left= 0;
- if (right >= columns)
- right= columns;
- if (left >= right)
- return;
- top -= win->offset;
- bottom -= win->offset;
- if (top < win->top)
- top= win->top;
- if (bottom > win->bottom)
- bottom= win->bottom;
- for (v= top; v < bottom; ++v) {
- int k= textlen[v];
- char *text= textline[v];
- if (k > right)
- k= right;
- while (--k >= left)
- text[k]= ' ';
- texttouched[v]= TRUE;
- }
- }
-